package com.autonavi.yunda.yunji.controller;

import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.controller.interceptor.NeedOperationLog;
import com.autonavi.yunda.yunji.core.enums.OperationRecordType;
import com.autonavi.yunda.yunji.core.enums.OperationRecordType.ComponentSubType;
import com.autonavi.yunda.yunji.core.enums.PartUnitInterfaceStatus;
import com.autonavi.yunda.yunji.core.enums.PartUnitTestStatus;
import com.autonavi.yunda.yunji.core.enums.UserPermission;
import com.autonavi.yunda.yunji.core.model.condition.PartUnitQueryCondition;
import com.autonavi.yunda.yunji.core.model.dto.PartUnitDTO;
import com.autonavi.yunda.yunji.core.model.dto.UserDTO;
import com.autonavi.yunda.yunji.core.model.mappers.PartUnitMapper;
import com.autonavi.yunda.yunji.core.model.vo.PartUnitExtraData;
import com.autonavi.yunda.yunji.core.service.PartUnitService;
import com.autonavi.yunda.yunji.core.service.thirdpartyservice.YuncangService;
import com.autonavi.yunda.yunji.core.service.thirdpartyservice.vo.TagVO;
import com.autonavi.yunda.yunji.core.vo.response.PartUnitPageVO;
import com.autonavi.yunda.yunji.core.vo.response.PartUnitVO;
import com.autonavi.yunda.yunji.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/apiPartUnit")
public class PartUnitController {
    @Resource
    private PartUnitService partUnitService;
    @Resource
    private YuncangService yuncangService;
    @Resource
    private BucUserService bucUserService;
    @Resource
    private OperationRecordService operationRecordService;
    @Resource
    private BPMSFlowService bpmsFlowService;
    @Resource
    private PartUnitMapper partUnitMapper;
    @Resource
    private FactoryUserService factoryUserService;
    @Resource
    private UserService userService;

    @Value("${yunji.bpms.instance.flow.url}")
    private String approvalFlowUrl;


    @NeedOperationLog(operationName = "apiPartUnit.import")
    @PostMapping("/import")
    public Long add(@RequestBody PartUnitVO partUnitVO) {
        AmapPreconditions.checkArgument(Objects.nonNull(partUnitVO) && partUnitVO.addValidate());
        String operatorId = bucUserService.getCurEmployeeIdOrNull();
        Map<Long, TagVO> tagIdMap = yuncangService.listOfAllTags()
                .stream().collect(Collectors.toMap(TagVO::getId, x -> x));
        PartUnitDTO dto = partUnitVO.toAddDto(tagIdMap, operatorId);
        dto.setBdId(factoryUserService.getCurrentUserBdId());
        Long id = partUnitService.add(dto);
        operationRecordService.add(OperationRecordType.ComponentSubType.CREATE, String.valueOf(id));
        return id;
    }

    @NeedOperationLog(operationName = "apiPartUnit.update")
    @PostMapping("/update")
    public void update(@RequestBody PartUnitVO partUnitVO) {
        AmapPreconditions.checkArgument(Objects.nonNull(partUnitVO));
        AmapPreconditions.checkArgumentForUser(partUnitVO.getId() != null, "id 不能为空");
        PartUnitDTO dto = partUnitService.findByIdOrThrow(partUnitVO.getId());
        AmapPreconditions.checkArgumentForUser(dto.getStatus() != PartUnitInterfaceStatus.PUBLISHED, "已发布的接口不能更新");
        String operatorId = bucUserService.getCurEmployeeIdOrNull();
        Map<Long, TagVO> tagIdMap = yuncangService.listOfAllTags()
                .stream().collect(Collectors.toMap(TagVO::getId, x -> x));
        UpdateWrapper<PartUnitDTO> updateWrapper = partUnitVO.toUpdateWrapper(tagIdMap, operatorId);
        partUnitService.update(updateWrapper);
        operationRecordService.add(ComponentSubType.UPDATE, String.valueOf(partUnitVO.getId()));

    }

    @NeedOperationLog(operationName = "apiPartUnit.list")
    @PostMapping("/list")
    public PartUnitPageVO listByPage(@RequestBody PartUnitQueryCondition condition) {
        AmapPreconditions.checkArgument(Objects.nonNull(condition) && condition.validate());
        Page<PartUnitDTO> page = new Page<>(condition.getPageNo(), condition.getPageSize());
        QueryWrapper<PartUnitDTO> queryWrapper = condition.getQueryWrapper();
        Long bdId = factoryUserService.getCurrentUserBdId();
        if (bdId != null) {
            queryWrapper.eq("bd_id", bdId);
        }
        Page<PartUnitDTO> queryResult = partUnitMapper.selectPage(page, queryWrapper);
        return new PartUnitPageVO(page.getRecords(), queryResult.getTotal(), approvalFlowUrl);
    }

    @GetMapping("/sync")
    @NeedOperationLog(operationName = "apiPartUnit.sync")
    public void syncToYuncang(@RequestParam Long id) {
        String operatorId = bucUserService.getCurEmployeeIdOrNull();
        partUnitService.syncToYuncang(id, operatorId);
        operationRecordService.add(ComponentSubType.SYNC, id.toString());
    }

    @GetMapping("/publish")
    @NeedOperationLog(operationName = "apiPartUnit.publish")
    public void publish(@RequestParam Long id) {
        String operatorId = bucUserService.getCurEmployeeIdOrNull();
        partUnitService.publish(id, operatorId);
        operationRecordService.add(ComponentSubType.PUBLISH, id.toString());
    }

    @GetMapping("/submitShelf")
    @NeedOperationLog(operationName = "apiPartUnit.submitShelf")
    public void submitShelf(@RequestParam Long id, @RequestParam String procInstId) {
        partUnitService.submitShelf(id, procInstId);
        operationRecordService.add(ComponentSubType.SUBMIT_SHELF, id.toString());
    }

    @NeedOperationLog(operationName = "apiPartUnit.delete")
    @GetMapping("delete")
    public void delete(@RequestParam Long id) {
        partUnitService.deleteById(id);
        operationRecordService.add(OperationRecordType.ProjectSubType.DELETE, id.toString());
    }

    @NeedOperationLog(operationName = "interface.submitTest")
    @GetMapping("submitTest")
    public String submitTest(@RequestParam Long id, @RequestParam(required = false) String testComment) {
        PartUnitDTO dto = partUnitService.findByIdOrThrow(id);
        AmapPreconditions.checkArgumentForUser(dto.getStatus() != PartUnitInterfaceStatus.PUBLISHED, "已发布的接口不能提交测试");
        List<UserDTO> userList = userService.listUserByPermission(UserPermission.COMPONENT_TEST_REVIEW);
        AmapPreconditions.checkArgumentForUser(!userList.isEmpty(), "审核人未配置，请联系管理员配置零部件测试审核人员");
        List<String> approvalUser = userList.stream().map(UserDTO::getUserId).collect(Collectors.toList());
        String testBPMSFlowId = bpmsFlowService.startTestBPMSFlow(id, bucUserService.getCurEmployeeId(), approvalUser, testComment);
        PartUnitExtraData extraData = dto.getExtraData();
        extraData.setTestBPMSFlowId(testBPMSFlowId);
        extraData.setTestStatus(PartUnitTestStatus.TESTING);
        partUnitService.updateExtraData(id, extraData);
        operationRecordService.add(OperationRecordType.ProjectSubType.TEST, id.toString());
        return testBPMSFlowId;
    }

}
